package com.ryanm.sage;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URL;
import java.util.Date;

/**
 * Attempts to repeatedly launch the sage, logging errors that ended the last 5
 * sessions. Sessions are launched in a separate process for robustness
 * 
 * @author ryanm
 */
public class Persist {
	/**
	 * @param args
	 */
	public static void main( String[] args ) {
		int run = 0;
		int limit = 5;

		while( true ) {
			// find the location of the jar
			URL jarLoc =
					SheevaSage.class.getProtectionDomain().getCodeSource()
							.getLocation();

			ProcessBuilder pb =
					new ProcessBuilder( "java", "-cp", jarLoc.getPath(),
							SheevaSage.class.getName(), args[ 0 ] );
			try {
				System.out.println( "Starting at " + new Date().toString() );
				final Process p = pb.start();

				OutPipe out = new OutPipe( p.getInputStream() );
				ErrPipe err = new ErrPipe( p.getErrorStream(), p );

				out.start();
				err.start();

				p.waitFor();

				out.shouldStop = true;
				out.interrupt();
				out.join();

				err.interrupt();
				err.join();

				System.out.println( "Process ended at " + new Date().toString()
						+ " with code " + p.exitValue() );
			}
			catch( IOException e ) {
				// command is wrong
				System.err.println( "Exiting due to" );
				e.printStackTrace();
				System.exit( 1 );
			}
			catch( InterruptedException ie ) {
				// waitfor or join have been interrupted
				System.err.println( "That shouldn't have happened!" );
				ie.printStackTrace();
				System.exit( 1 );
			}

			try {
				Thread.sleep( 10000 );
			}
			catch( InterruptedException e ) {
				e.printStackTrace();
			}

			run++;
			run %= limit;
		}
	}

	private static class OutPipe extends Thread {
		public boolean shouldStop = false;

		private final BufferedReader br;

		private OutPipe( InputStream is ) {
			br = new BufferedReader( new InputStreamReader( is ) );
			setDaemon( true );
		}

		@Override
		public void run() {
			try {
				String line = br.readLine();
				while( line != null && !shouldStop ) {
					System.out.print( "\t" );
					System.out.println( line );
					line = br.readLine();
				}
			}
			catch( IOException e ) {
				e.printStackTrace();
			}
		}
	}

	private static class ErrPipe extends Thread {
		private BufferedReader br;

		private Process process;

		private ErrPipe( InputStream is, Process p ) {
			br = new BufferedReader( new InputStreamReader( is ) );
			this.process = p;
			setDaemon( true );
		}

		@Override
		public void run() {
			try {
				br.readLine();
				process.destroy();
			}
			catch( IOException e ) {
				e.printStackTrace();
			}
		}
	}
}
